#include "GUI.h"
#include "Global.h"

CGUITextBox::CGUITextBox(GUI_PARAMS* params, GUI_COLORS* colors, GUI_SPRITES* sprites, bool _editable, bool _selectable, UINT _event, void* _dest, LPCSTR _text){
	Init(params, colors, sprites);
	m_bEditable=_editable;
	m_bSelectable=_selectable;
	m_pDest=_dest;
	m_Event=_event;
	m_Type=GUITYPE_TEXTBOX;
	m_Scrollx=0;
	m_Scrolly=0;
	SetText(_text);
	m_Caretx=m_MaxCaretx;
	m_Carety=m_MaxCarety;
	SyncSelStart();
	m_bCaretOn=true;
	m_CaretBlink=40;
};

CGUITextBox::~CGUITextBox(){};


bool CGUITextBox::WndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam ){
	switch(uMsg){
		// Keyboard messages
        case WM_KEYDOWN:
		case WM_CHAR:
        case WM_SYSKEYDOWN:
        case WM_KEYUP:
        case WM_SYSKEYUP:
			return HandleKeyboard( uMsg, wParam, lParam );
		//Mouse Messages
				case WM_MOUSEMOVE:
        case WM_LBUTTONDOWN:
        case WM_LBUTTONUP:
        case WM_MBUTTONDOWN:
        case WM_MBUTTONUP:
        case WM_RBUTTONDOWN:
        case WM_RBUTTONUP:
        case WM_XBUTTONDOWN:
        case WM_XBUTTONUP:
        case WM_LBUTTONDBLCLK:
        case WM_MBUTTONDBLCLK:
        case WM_RBUTTONDBLCLK:
        case WM_XBUTTONDBLCLK:
        case WM_MOUSEWHEEL:
			return HandleMouse( uMsg, wParam, lParam );
		default:
			return false;
	}
}
bool CGUITextBox::HandleKeyboard( UINT uMsg, WPARAM wParam, LPARAM lParam ) {
	if(GetFocus() && wParam==m_Hotkey){
		OnHotkey();
		return true;
	}
if(GetFocus() && m_bSelectable)
	switch(uMsg){
		case WM_KEYDOWN:
			switch( wParam ){
				case VK_UP:
					PlaceCaret(m_Caretx, m_Carety-1);
					if( GetKeyState( VK_SHIFT ) >= 0 )
						SyncSelStart();
					break;
				case VK_DOWN:
					PlaceCaret(m_Caretx, m_Carety+1);
					if( GetKeyState( VK_SHIFT ) >= 0 )
						SyncSelStart();
					break;
				case VK_LEFT:
					PlaceCaret(m_Caretx-1, m_Carety);
					if( GetKeyState( VK_SHIFT ) >= 0 )
						SyncSelStart();
					break;
				case VK_RIGHT:
					PlaceCaret(m_Caretx+1, m_Carety);
					if( GetKeyState( VK_SHIFT ) >= 0 )
						SyncSelStart();
					break;
			default:
				break;
			}
			break;
        case WM_CHAR:
			switch( wParam ){
				case VK_BACK:
					if(m_Caretx==m_SelStartx && m_Carety==m_SelStarty)
						DeleteTextAtCaret();
					else
						DeleteSelectionText();
					break;
				case VK_RETURN:
					if(VK_RETURN!=m_Hotkey){
						if(m_Caretx==m_SelStartx && m_Carety==m_SelStarty)
						AddChar('\n');
						SyncSelStart();
					}
					break;
				case 24: // Ctrl-X Cut
                case VK_CANCEL: // Ctrl-C Copy
                case 22: // Ctrl-V Paste
                case 26:  // Ctrl Z
                case 2:   // Ctrl B
                case 14:  // Ctrl N
                case 19:  // Ctrl S
                case 4:   // Ctrl D
                case 6:   // Ctrl F
                case 7:   // Ctrl G
                case 10:  // Ctrl J
                case 11:  // Ctrl K
                case 12:  // Ctrl L
                case 17:  // Ctrl Q
                case 23:  // Ctrl W
                case 5:   // Ctrl E
                case 18:  // Ctrl R
                case 20:  // Ctrl T
                case 25:  // Ctrl Y
                case 21:  // Ctrl U
                case 9:   // Ctrl I
                case 15:  // Ctrl O
                case 16:  // Ctrl P
                case 27:  // Ctrl [
                case 29:  // Ctrl ]
                case 28:  // Ctrl \ 
					break;
				default:
					if(m_bEditable){
						AddChar((char)wParam);
						SyncSelStart();
					}
			}
			return true;
		default:
			return false;
	}

	return false;
}
bool CGUITextBox::HandleMouse( UINT uMsg, WPARAM wParam, LPARAM lParam ) {
	POINT MousePos;
	GetCursorPos(&MousePos);
	switch(uMsg){
		case WM_MOUSEMOVE:
			if(!m_bMouseOver && PtInBB(MousePos) && GetVisible()){
				OnMouseEnter();
			}if(m_bMouseOver && !PtInBB(MousePos)){
				OnMouseLeave();
			}
			//if(Parent && ((CGUIWindow*)Parent)->GetFocusElement()==this)
				//return true;

			break;
		case WM_LBUTTONDOWN:
			if(m_bMouseOver){
				if(!m_bButtonDown){
					if(GetFocus() || RequestFocus())
						m_bButtonDown=true;

				}
				PlaceCaret(MousePos);
				return true;
			}
			break;
		case WM_LBUTTONUP:
			if(m_bButtonDown && m_bMouseOver){
				
			}
			m_bButtonDown=false;
			break;
		case WM_MOUSEWHEEL:
			if(m_bMouseOver){
				if((int)wParam>0){//Scroll Up
					m_Scrolly=max((int)m_Scrolly-1, 0);
				}else{
					m_Scrolly=min((int)m_Scrolly+1, max((int)m_MaxCarety-((int)(m_height/13))+1, 0));
				}
				//m_Scrollx=min(max(m_Scrollx, 0), m_MaxCaretx+((int)(width/8)));
				SetTextDraw();
			}
			break;
		default:
			if(m_bMouseOver)
				return true;
			return false; 
	}
	return false;
}

void CGUITextBox::AddText(std::string _text){
	UINT c=0;
	UINT index=0;
	/*std::string temp=m_Text;
	while(temp.find("\n")!=temp.npos){
		index+=(UINT)temp.find("\n");
		if((height/12-2)+Scroll==c || (Scroll==0 && c==m_Carety)){
			m_Text=m_Text.substr(0, index)+m_Text.substr(index+1);
			break;
		}
		c++;
	}*/
	//SetText(m_Text.substr(0,
}
void CGUITextBox::SetText(std::string _text){ 
	std::string t=_text;
	m_MaxCarety=-1;
	m_Scrolly=0;
	m_Text.clear();

	if(t.find("\n")==t.npos){
		AddLine(_text);
	}else{
		while(t.find("\n")!=t.npos){
			AddLine(t.substr(0, t.find("\n")-1));
			t=t.substr(t.find("\n")+1);
		}
	}
}
void CGUITextBox::SetTextDraw(){
	m_TextDraw="";	
	for(UINT a=m_Scrolly; a<m_Scrolly+(int)(m_height/13); a++){
		if(a>m_MaxCarety || a>=m_Text.size())
			break;
		m_TextDraw+=m_Text[a]+"\n";
	}
}
void CGUITextBox::DeleteTextAtCaret(){
	if(m_Caretx!=0){
		m_Text[m_Carety]=m_Text[m_Carety].substr(0, m_Caretx-1)+m_Text[m_Carety].substr(m_Caretx);
		PlaceCaret(m_Caretx-1, m_Carety);
	}else if(m_Carety>0){
		int temp=(int)m_Text[m_Carety-1].length();
		m_Text[m_Carety-1]+=m_Text[m_Carety];
		for(UINT a=m_Carety;a<m_MaxCarety;a++)
			m_Text[a]=m_Text[a+1];
		m_MaxCarety--;
		m_Text.pop_back();
		PlaceCaret(temp, m_Carety-1);
	}
	SyncSelStart();
}
void CGUITextBox::DeleteSelectionText(){
/*if(!(m_Caretx==0 && m_Carety==0))
	if(m_Caretx==m_SelStartx && m_Carety==m_SelStarty){
		if(m_Caretx==0){
			if(m_Carety==m_MaxCarety)
				SetText(m_Text.substr(0,(int)m_Text.length()-2));
			else{
				UINT c=0;
				UINT index=0;
				std::string temp=m_Text;
				while(temp.find("\n")!=temp.npos){
					index+=(UINT)temp.find("\n");
					if(19+Scroll==c || (Scroll==0 && c==m_Carety)){
						m_Text=m_Text.substr(0, index+m_Caretx)+m_Text.substr(index+m_Caretx+1);
						break;
					}
					c++;
				}
			}

		}else{
			m_Text=m_Text.substr(0,m_Caretx-1)+m_Text.substr(m_Caretx);
			TextDraw=TextDraw.substr(0,m_Caretx-1)+TextDraw.substr(m_Caretx);
			m_Caretx--;
		}
		m_SelStartx=m_Caretx;
		m_SelStarty=m_Carety;
	}else{*/
		/*TextDraw=m_Text;
		CaretTextline=m_Text;
		m_Carety=0;
		while(CaretTextline.find("\n")!=CaretTextline.npos){
			m_Carety++;
			CaretTextline=CaretTextline.substr(CaretTextline.find("\n")+1);
			if(m_Carety>19){
				m_Carety--;
				TextDraw=TextDraw.substr(CaretTextline.find("\n")+1);
			}
		}*/
	//}

};
void CGUITextBox::PlaceCaret(int _x, int _y){
	m_Carety=min((UINT)max(0, _y), m_MaxCarety);
	m_MaxCaretx=(UINT)m_Text[m_Carety].length();
	m_Caretx=min((UINT)max(0, _x), m_MaxCaretx);
	
	if(m_Caretx>=m_Scrollx+((int)(m_width/8))){
		m_Scrollx=m_Caretx-((int)(m_width/8))+1;
	}else if(m_Caretx<m_Scrollx){
		m_Scrollx=m_Caretx;
	}
	if(m_Carety>=m_Scrolly+((int)(m_height/13))){
		m_Scrolly=m_Carety-((int)(m_height/13))+1;
	}else if(m_Carety<m_Scrolly){
		m_Scrolly=m_Carety;
	}
	SetTextDraw();
	m_CaretBlink=30;
	m_bCaretOn=true;
}
void CGUITextBox::PlaceCaret(POINT _cursor){
	float dx=m_pos.x;
	float dy=m_pos.y;
	CGUIBase* p=m_pParent;
	while(p!=NULL){
		dx+=p->GetPos().x;
		dy+=p->GetPos().y;
		p=p->GetParent();
	}
	PlaceCaret((int)((float)(_cursor.x-dx-m_border-2)/(float)8+0.5f)+m_Scrollx, (int)((float)(_cursor.y-dy-m_border-2)/(float)13)+m_Scrolly);
}
void CGUITextBox::AddChar(char _char){
	
	if(_char!='\n'){
		m_Text[m_Carety]=m_Text[m_Carety].substr(0, m_Caretx)+_char+m_Text[m_Carety].substr(m_Caretx);
		m_MaxCaretx++;
		PlaceCaret(m_Caretx+1, m_Carety);
		if(m_Caretx-m_Scrollx>=((int)(m_width/8))){
			m_Scrollx++;
		}
	}else{
		m_MaxCarety++;
		m_Text.push_back("");
		for(UINT a=m_MaxCarety;a>m_Carety+1;a--)
			m_Text[a]=m_Text[a-1];
		m_Text[m_Carety+1]=m_Text[m_Carety].substr(m_Caretx);
		m_Text[m_Carety]=m_Text[m_Carety].substr(0, m_Caretx);
		PlaceCaret(0, m_Carety+1);
		if(m_Carety-m_Scrolly>=((int)(m_height/13))){
			m_Scrolly++;
		}
	}
}
void CGUITextBox::AddLine(std::string _text){
	m_MaxCarety++;
	m_Text.push_back(_text);

	if(m_MaxCarety>=((int)(m_height/13))){
		m_Scrolly++;
	}
	PlaceCaret(1000,1000);
}
void CGUITextBox::SyncSelStart(){
	m_SelStartx=m_Caretx;
	m_SelStarty=m_Carety;
}

bool CGUITextBox::RequestFocus() {
	if(m_pParent){
		if(CanHaveFocus()){
			return ((CGUIWindow*)m_pParent)->SetFocusElement(this);
		}
	}
	return false;
}
bool CGUITextBox::CanHaveFocus(){ return true; }
void CGUITextBox::OnFocusIn() { m_bHasFocus = true; }
void CGUITextBox::OnFocusOut() { m_bHasFocus = false; }
void CGUITextBox::OnMouseEnter() { 
//	SetCursor(g_pCursor);
	m_bMouseOver = true; 
}
void CGUITextBox::OnMouseLeave() { m_bMouseOver = false; }
void CGUITextBox::OnHotkey() {
	if(!(m_MaxCaretx==0 && m_MaxCarety==0)){
		OnGUIEvent(m_Type, m_Event, this, m_pDest);
		SetText("");
		PlaceCaret(0,0);
	}
}
void CGUITextBox::Step(){
	if(m_CaretBlink>0)
		m_CaretBlink--;
	else{
		m_CaretBlink=30;
		m_bCaretOn=!m_bCaretOn;
	}
	SyncSelStart();//Remove when u do selecting/copy/paste
}
void CGUITextBox::Draw(){
	if(GetVisible()){
		UpdateBB();
		if(m_pSprites && m_pSprites->BG)
			DrawSpriteExact(m_pSprites->BG, 0, m_drawpos);
		else
			DrawRectExact(m_drawpos, m_width, m_height, m_pColors->BG, m_border, m_pColors->Border);

		if(m_TextDraw!=""){
			DrawTextExact(g_pFontList->Courier12, m_TextDraw, V(m_drawpos.x+m_border+2, m_drawpos.y+m_border+3), m_pColors->Text);
		}
		if(GetFocus() && m_bSelectable && m_bCaretOn && !(m_Carety<m_Scrolly) && !(m_Carety>=m_Scrolly+((int)(m_height/13))))
			DrawRectExact(V(m_drawpos.x+m_border+2+(m_Caretx-m_Scrollx)*8, m_drawpos.y+m_border+2+(m_Carety-m_Scrolly)*13), 1, g_pFontList->Courier12->height+2, CLR_BLACK);

		if(!GetEnabled())
			DrawRectExact(m_drawpos, m_width, m_height, D3DCOLOR_ARGB(128, 128, 128, 128));
	}
}